package com.cyf.common.core.io;

import java.io.*;
import java.nio.charset.Charset;

/**
 *
 * 参考 org.springframework.util.StreamUtils
 * @author chenyifan
 * @create 2024-08-02 15:17
 */
public class IOUtil {

    public static final int BUFFER_SIZE = 4096;

    private static final byte[] EMPTY_CONTENT = new byte[0];

    /**
     * 将给定 InputStream 的内容复制到字节数组中。
     * 完成后使流保持打开状态
     * @param is 输入流
     * @return
     * @throws IOException
     */
    public static byte[] copyToByteArray(InputStream is) throws IOException {
        if (is == null) {
            return EMPTY_CONTENT;
        }
        // 里面实质是 new 了一个字节数组，不用关闭流
        ByteArrayOutputStream out = new ByteArrayOutputStream(BUFFER_SIZE);
        copy(is, out);
        return out.toByteArray();
    }

    /**
     * 将给定 InputStream 的内容复制到字符串。
     * @param is 输入流
     * @param charset 字符集
     * @return
     * @throws IOException
     */
    public static String copyToString(InputStream is, Charset charset) throws IOException {
        StringBuilder out = new StringBuilder(BUFFER_SIZE);
        InputStreamReader reader = new InputStreamReader(is, charset);
        char[] buffer = new char[BUFFER_SIZE];
        int charsRead;
        while ((charsRead = reader.read(buffer)) != -1) {
            out.append(buffer, 0, charsRead);
        }
        return out.toString();
    }

    /**
     * 将字符串的内容复制到给定的 OutputStream，完成后使流保持打开状态。
     * @param str 要复制的字符串
     * @param charset 字符集
     * @param os
     * @throws IOException
     */
    public static void copy(String str, Charset charset, OutputStream os) throws IOException {
        // 将字符的输出流按指定字符集转换为字节的输出流
        Writer writer = new OutputStreamWriter(os, charset);
        writer.write(str);
        writer.flush();
    }

    /**
     * 拷贝字节数组到输出流
     * @param bytes 字节数组
     * @param os 输出流
     * @throws IOException
     */
    public static void copy(byte[] bytes, OutputStream os) throws IOException {
        os.write(bytes);
        os.flush();
    }

    /**
     * 将给定 InputStream 的内容复制到给定的 OutputStream。
     * 完成后，使两个流都保持打开状态
     * @param is
     * @param os
     * @return 复制的字节数
     * @throws IOException
     */
    public static int copy(InputStream is, OutputStream os) throws IOException {
        int byteCount = 0;
        byte[] buffer = new byte[BUFFER_SIZE];
        int bytesRead;
        while ((bytesRead = is.read(buffer)) != -1) {
            os.write(buffer, 0, bytesRead);
            byteCount += bytesRead;
        }
        return byteCount;
    }

    /**
     * 关闭多个流
     * @param cls
     */
    public static void closeMulti(Closeable... cls) {
        for (Closeable c : cls) {
           close(c);
        }
    }

    /**
     * 关闭单个流
     * @param c
     */
    public static void close(Closeable c) {
        if (c != null) {
            try {
                c.close();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    }
}
